package obecto.tween
{
	import flash.utils.Dictionary;
	
	import obecto.tween.easing.PennerEasing;
	
	public class AbstractTween
	{
		private var _initialValues : Dictionary;
	
		private var _tweeningProperties : Dictionary;
		public function get tweeningProperties() : Dictionary
		{
			return _tweeningProperties;
		}
		private var _target : Object;
		public function get target() : Object
		{
			return _target;
		}
		
		public function set target(value : Object) : void
		{
			_target = value;	
		}
		
		public var duration : Number = 10;
		
		/**
		* Generates elastic easing in tween where equation for motion is based on Hooke's Law of <code>F = -kd</code>.
		* @param t		time
		* @param b		beginning position
		* @param c		total change in position
		* @param d		duration of the tween
		* @param a		(optional) amplitude, or magnitude of wave's oscillation
		* @param p		(optional) period
		* @return		final position
		*/
		public var easingEquation : Function = PennerEasing.linear;
		
		public var tweenFinishedDelegate : Function;
		public var tweenUpdateDelegate : Function;
		
		public var option1 : Number;
		public var option2 : Number;
		
		protected var _durationElapsed : Number = 0;
		public function get durationElapsed() : Number
		{
			return _durationElapsed;
		}
		
		public function get finished() : Boolean
		{
			return (_durationElapsed >= duration);
		}
		
		public function AbstractTween(target : Object, tweeningProperties : Dictionary) 
		{
			super();
			
			_target = target;
				
			_tweeningProperties = new Dictionary();
			_initialValues = new Dictionary();
			
			for (var key : Object in tweeningProperties)
			{
				_initialValues[key] = _target[key];
				_tweeningProperties[key] = tweeningProperties[key];
			}
		}
		
		public function update() : void
		{
			increaseDurationElapsed();
			
			for (var key : Object in _tweeningProperties)
			{
				_target[key] = easingEquation(
					_durationElapsed,
					_initialValues[key],
					_tweeningProperties[key] - _initialValues[key],
					duration,
					option1,
					option2
				);
			}
			
			tweenUpdateDelegate();
			
			if (finished)
			{
				tweenFinishedDelegate();
			}
		}	
		
		virtual protected function increaseDurationElapsed() : void 
		{
			throw new Error("Not implemented");
		}

	}
}